# -*- coding: utf-8 -*-
"""
Created on Mon Jul 7 17:00:00 2018

@author: JockJo
"""


import os
import xml.etree.cElementTree as ET
import re
import mongo_util


class XMLUTIL:
    # 迭代xml文件转换为字典形式
    def xml_iterparse(self, root):
        root_dict = {}
        if root.attrib: #and root.item is not '\n':  # 获取该标签的属性值
            root_dict['{}.attrib'.format(root.tag)] = root.attrib
        if root.text is not None and root.text is not '\n':
            root_dict['{}.text'.format(root.tag)] = root.text
        for child in root:
            if child.tag is not None:
                root_dict[child.tag] = self.xml_iterparse(child)
        return root_dict

    def xmlstr_print(self, xml_str, filename, father_filename):
        filepath = 'D:\documents\mydoc\code\python\parser\{}\{}\{}.xml'.format(father_filename, 'str',filename)  # single_zip_name   str  filename
        path = 'D:\documents\mydoc\code\python\parser\{}\{}'.format(father_filename, 'str')
        isExists = os.path.exists(path)
        if not isExists:
            try:
                os.makedirs(path)
            except:
                print("[dir error]: {}".format(path))
        try:
            f = open(filepath, 'w+')  # 文件可读可写 不存在则创建文件
            print(xml_str, file=f)
        except Exception as e:
            print("[file_str error] {}:{}".format(filename, e))

    def xmljson_print(self, xml_json, filename, father_filename):
        filepath = 'D:\documents\mydoc\code\python\parser\{}\{}\{}.json'.format(father_filename, 'json',filename)  # single_zip_name   str  filename
        path = 'D:\documents\mydoc\code\python\parser\{}\{}'.format(father_filename, 'json')
        isExists = os.path.exists(path)
        if not isExists:
            try:
                os.makedirs(path)
            except:
                print("[dir error]: {}".format(path))
        try:
            f = open(filepath, 'w+')  # 文件可读可写 不存在则创建文件
            print(xml_json, file=f)
        except Exception as e:
            print("[file_json error] {}:{}".format(filename, e))

    def xml_to_dict(self, xml_str, filename):
        try:
            root = ET.XML(xml_str)
            root_dict = {}
            if root.tag is not None:
                root_dict[root.tag] = self.xml_iterparse(root)
            print(root_dict)
            return root_dict
        except Exception as e:
            print("[xml error] {}:{}".format(filename, e))

    def xml_to_mongodb(self, xml_str, mongo_db=None, mongo_collection=None, client=None, port=None):
        #解析xml
        item = self.xml_to_item(xml_str)
        # return item
        db = mongo_util.Mongo(mongo_db=mongo_db)
        db.store_item(collection_name=mongo_collection,item=item)

    #转换成可以存储到mongodb中的格式
    def xml_to_item(self, xml_str):
        item = {}
        parties = self.extract_text(r'<us-parties[^>]*>[\s\S]*</us-parties>', r'<us-parties[^>]*>', r'</us-parties>',
                                    xml_str)
        for party in parties:
            # extract applicant
            us_applicants = {}
            applicants = self.extract_text(r'<us-applicant[^>]*>[\s\S]*</us-applicant>',
                                           r'<us-applicant[^>]*>', r'</us-applicant>',
                                           party)
            i = 0
            for applicant in applicants:
                us_applicant = {}
                # extract name of applicant
                org_name = self.extract_text(r'<orgname[^>]*>[\s\S]*</orgname>',
                                             r'<orgname[^>]*>', r'</orgname>',
                                             applicant)
                if org_name[0] is not 'unknown':
                    us_applicant['name'] = org_name[0]
                else:
                    last_name = self.extract_text(r'<last-name[^>]*>[\s\S]*</last-name>',
                                                  r'<last-name[^>]*>', r'</last-name>',
                                                  applicant)[0]
                    first_name = self.extract_text(r'<first-name[^>]*>[\s\S]*</first-name>',
                                                   r'<first-name[^>]*>', r'</first-name>',
                                                   applicant)[0]
                    us_applicant['name'] = last_name + ' ' + first_name
                # extract city of applicant
                us_applicant['city'] = self.extract_text(r'<city[^>]*>[\s\S]*</city>',
                                                         r'<city[^>]*>', r'</city>',
                                                         applicant)[0]
                # extract state of applicant
                us_applicant['state'] = self.extract_text(r'<state[^>]*>[\s\S]*</state>',
                                                          r'<state[^>]*>', r'</state>',
                                                          applicant)[0]
                # extract country of applicant
                us_applicant['country'] = self.extract_text(r'<country[^>]*>[\s\S]*</country>',
                                                            r'<country[^>]*>', r'</country>',
                                                            applicant)[0]
                us_applicants['applicant_{}'.format(i)] = us_applicant
                i += 1
            # extract inventor
            us_inventors = {}
            inventors = self.extract_text(r'<inventor[^>]*>[\s\S]*</inventor>',
                                          r'<inventor[^>]*>', r'</inventor>',
                                          party)
            i = 0
            for inventor in inventors:
                us_inventor = {}
                last_name = self.extract_text(r'<last-name[^>]*>[\s\S]*</last-name>',
                                              r'<last-name[^>]*>', r'</last-name>',
                                              inventor)[0]
                first_name = self.extract_text(r'<first-name[^>]*>[\s\S]*</first-name>',
                                               r'<first-name[^>]*>', r'</first-name>',
                                               inventor)[0]
                us_inventor['name'] = last_name + ' ' + first_name
                # extract city of inventor
                us_inventor['city'] = self.extract_text(r'<city[^>]*>[\s\S]*</city>',
                                                        r'<city[^>]*>', r'</city>',
                                                        inventor)[0]
                # extract state of inventor
                us_inventor['state'] = self.extract_text(r'<state[^>]*>[\s\S]*</state>', r'<state[^>]*>',
                                                         r'</state>',
                                                         inventor)[0]
                # extract country of inventor
                us_inventor['country'] = self.extract_text(r'<country[^>]*>[\s\S]*</country>',
                                                           r'<country[^>]*>', r'</country>',
                                                           inventor)[0]
                us_inventors['inventor_{}'.format(i)] = us_inventor
                i += 1
            # extract agent
            us_agents = {}
            agents = self.extract_text(r'<agent[^>]*>[\s\S]*</agent>',
                                       r'<agent[^>]*>', r'</agent>',
                                       party)
            i = 0
            for agent in agents:
                us_agent = {}
                org_name = self.extract_text(r'<orgname[^>]*>[\s\S]*</orgname>',
                                             r'<orgname[^>]*>', r'</orgname>',
                                             agent)
                if org_name[0] is not 'unknown':
                    us_agent['name'] = org_name[0]
                else:
                    last_name = self.extract_text(r'<last-name[^>]*>[\s\S]*</last-name>',
                                                  r'<last-name[^>]*>', r'</last-name>',
                                                  agent)[0]
                    first_name = self.extract_text(r'<first-name[^>]*>[\s\S]*</first-name>',
                                                   r'<first-name[^>]*>', r'</first-name>',
                                                   agent)[0]
                    us_agent['name'] = last_name + ' ' + first_name
                # extract country of agent
                us_agent['country'] = self.extract_text(r'<country[^>]*>[\s\S]*</country>',
                                                        r'<country[^>]*>', r'</country>',
                                                        agent)[0]
                us_agents['agent_{}'.format(i)] = us_agent
                i += 1

            item['us_applicants'] = us_applicants
            item['us_inventors'] = us_inventors
            item['us_agents'] = us_agents

        #extract assignee
        assignees = self.extract_text(r'<assignee[^>]*>[\s\S]*</assignee>',
                                      r'<assignee[^>]*>', r'</assignee>',
                                      xml_str)
        us_assignees = {}
        i = 0
        for assignee in assignees:
            us_assignee = {}
            org_name = self.extract_text(r'<orgname[^>]*>[\s\S]*</orgname>',
                                         r'<orgname[^>]*>', r'</orgname>',
                                         assignee)
            if org_name[0] is not 'unknown':
                us_assignee['name'] = org_name[0]
            else:
                last_name = self.extract_text(r'<last-name[^>]*>[\s\S]*</last-name>',
                                              r'<last-name[^>]*>', r'</last-name>',
                                              assignee)[0]
                first_name = self.extract_text(r'<first-name[^>]*>[\s\S]*</first-name>',
                                               r'<first-name[^>]*>', r'</first-name>',
                                               assignee)[0]
                us_assignee['name'] = last_name + ' ' + first_name
            # extract city of assignee
            us_assignee['city'] = self.extract_text(r'<city[^>]*>[\s\S]*</city>',
                                                    r'<city[^>]*>', r'</city>',
                                                    assignee)[0]
            # extract country of assignee
            us_assignee['country'] = self.extract_text(r'<country[^>]*>[\s\S]*</country>',
                                                       r'<country[^>]*>', r'</country>',
                                                       assignee)[0]
            us_assignees['assignee_{}'.format(i)] = us_assignee
            i += 1
        item['us_assignee'] = us_assignees
        # extract abstract
        abstract = self.extract_text(r'<abstract[^>]*>[\s\S]*</abstract>',
                                     r'<abstract[^>]*>', r'</abstract>',
                                     xml_str)
        item['abstract'] = abstract[0]
        item['abstract'] = re.sub(r'<[^>]*>', '', item['abstract'])

        # extract descreption
        description = self.extract_text(r'<description[^>]*>[\s\S]*</description>',
                                        r'<description[^>]*>', r'</description>',
                                        xml_str)
        item['description'] = description[0]
        item['description'] = re.sub(r'<[^>]*>', '', item['description'])

        # extract claims
        claims = self.extract_text(r'<claims[^>]*>[\s\S]*</claims>',
                                   r'<claims[^>]*>', r'</claims>',
                                   xml_str)
        item['claim'] = claims[0]
        item['claim'] = re.sub(r'<[^>]*>', '', item['claim'])

        # extract title
        title = self.extract_text(r'<invention-title[^>]*>[\s\S]*</invention-title>',
                                  r'<invention-title[^>]*>', r'</invention-title>',
                                  xml_str)
        item['title'] = title[0]
        item['title'] = re.sub(r'<[^>]*>', '', item['title'])

        # extract us-patent-grant
        base_info = {}
        us_patent_grant = re.findall(r'<us-patent-grant[^>]*>', xml_str)
        if us_patent_grant.__len__() is not 0:
            us_patent_grant = us_patent_grant[0]
            base_info['dtd_version'] = self.extract_attribute(r'dtd-version="[^"]*"', us_patent_grant)
            base_info['status'] = self.extract_attribute(r'status="[^"]*"', us_patent_grant)
            base_info['id'] = self.extract_attribute(r'id="[^"]*"', us_patent_grant)
            base_info['country'] = self.extract_attribute(r'country="[^"]*"', us_patent_grant)
            base_info['date_produced'] = self.extract_attribute(r'date-produced="[^"]*"', us_patent_grant)
            base_info['date_publ'] = self.extract_attribute(r'date-publ="[^"]*"', us_patent_grant)
            item['base_info'] = base_info
        else:
            item['base_info'] = 'unknonw'
        # extract application-reference
        us_application_references = {}
        application_references = self.extract_text(r'<application-reference[^>]*>[\s\S]*</application-reference>',
                                                   r'<application-reference[^>]*>', r'</application-reference>',
                                                   xml_str)
        for application_reference in application_references:
            us_application_reference = {}
            us_application_reference['country'] = self.extract_text(r'<country[^>]*>[\s\S]*</country>',
                                                                    r'<country[^>]*>', r'</country>',
                                                                    application_reference)[0]
            us_application_reference['doc_number'] = self.extract_text(r'<doc-number[^>]*>[\s\S]*</doc-number>',
                                                                       r'<doc-number[^>]*>', r'</doc-number>',
                                                                       application_reference)[0]
            item['doc_number'] = us_application_reference['doc_number']
            us_application_reference['date'] = self.extract_text(r'<date[^>]*>[\s\S]*</date>',
                                                                 r'<date[^>]*>', r'</date>',
                                                                 application_reference)[0]
            us_application_references[us_application_reference['doc_number']] = us_application_reference
        item['us_application_reference'] = us_application_references

        # extract classification
        us_classification = {}
        # 首先判断是否有ipcr分类
        class_ipcr = self.extract_text(r'<classification-ipcr[^>]*>[\s\S]*</classification-ipcr>',
                                       r'<classification-ipcr[^>]*>',
                                       r'</classification-ipcr>', xml_str)
        if class_ipcr[0] is not 'unknown':
            classification = class_ipcr[0]
            ipc_version_indicator = self.extract_text(r'<ipc-version-indicator[^>]*>[\s\S]*</ipc-version-indicator>',
                                                      r'<ipc-version-indicator[^>]*>', r'</ipc-version-indicator>',
                                                      classification)
            us_classification['ipc_version_indicator'] = ipc_version_indicator[0]
            us_classification['ipc_version_indicator'] = re.sub(r'<[^>]*>', '',
                                                                us_classification['ipc_version_indicator'])
            section = self.extract_text(r'<section>[\s\S]*</section>',
                                        r'<section>', r'</section>',
                                        classification)[0]
            the_class = self.extract_text(r'<class>[\s\S]*</class>',
                                          r'<class>', r'</class>',
                                          classification)[0]
            subclass = self.extract_text(r'<subclass>[\s\S]*</subclass>',
                                         r'<subclass>', r'</subclass>',
                                         classification)[0]
            main_group = self.extract_text(r'<main-group>[\s\S]*</main-group>',
                                           r'<main-group>', r'</main-group>',
                                           classification)[0]
            subgroup = self.extract_text(r'<subgroup>[\s\S]*</subgroup>',
                                         r'<subgroup>', r'</subgroup>',
                                         classification)[0]
            us_classification['class'] = "ipcr" + ":" + section + the_class + subclass + r" " + main_group + r"/" + subgroup

        else:
            class_national = self.extract_text(r'<classification-national[^>]*>[\s\S]*</classification-national>',
                                           r'<classification-national[^>]*>',
                                           r'</classification-national>', xml_str)
            class_national = class_national[0]
            class_national_country = self.extract_text(r'<country[^>]*>[\s\S]*</country>',
                                                       r'<country[^>]*>', r'</country>',
                                                       class_national)[0]
            main_class =  self.extract_text(r'<main-classification[^>]*>[\s\S]*</main-classification>',
                                            r'<main-classification[^>]*>', r'</main-classification>',
                                            class_national)[0]
            us_classification['class'] = "national" + ":" + class_national_country + " " + main_class
        item['us_classification'] = us_classification
        return item

    #extract text from tag
    def extract_text(self, match_str, tag_head, tag_tail, src_str):
        tag = re.findall(match_str, src_str)
        if tag.__len__() is 0:
            tag = ['unknown']
            return tag
        tag = tag[0]
        #可能存在多个tag，转换成数组
        #去掉头部
        tag = re.sub(tag_head, '', tag)
        #去掉尾部，直接采用split，转换成数组
        tag = tag.split(tag_tail)
        tag = tag[:-1]
        return tag

    #extract attribute from tag
    def extract_attribute(self, attribute, tag):
        attribute_text = re.findall(attribute, tag)
        if attribute_text.__len__() is 0:
            attribute_text = ['unknown']
            return attribute_text
        attribute_text = re.findall(r'"[^"]*"', attribute_text[0])
        attribute_text = attribute_text[0].replace(r'"', '')
        return attribute_text
